<template>
  <div class="product-container">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-container">
      <div class="loading-text">Loading...</div>
    </div>

    <!-- 空状态 -->
    <div v-else-if="!hasProducts" class="empty-container">
      <el-empty description="No Data ..." />
    </div>

    <div v-else class="masonry-container" ref="masonryContainer">
      <div
        v-for="product in products"
        :key="product.id"
        class="masonry-item text-[#222]"
        @click="viewProduct(product)">
        <div class="product-image relative">
          <img
            v-img-zoom
            :src="product.thumbnail?.url"
            :alt="product.name"
            :style="getImageStyle(product.thumbnail)" />
        </div>
        <div class="product-info">
          <h3 class="product-name">{{ product.title }}</h3>
          <div class="product-description">
            <div
              class="overflow-hidden text-ellipsis whitespace-nowrap leading-[1.2]"
              :class="{ 'max-w-[60%]': product.tags.length > 0 }">
              {{ product.caption }}
            </div>
            <div class="tag_list_view" v-if="product.tags.length > 0">
              <span
                v-slide-underline
                class="line max-w-[100%] text-[#222] ml-2 overflow-hidden text-ellipsis whitespace-nowrap"
                v-for="tag in product.tags"
                :key="tag.id"
                @click.stop="handleTagClick(tag)">
                # {{ tag.name }}
              </span>
            </div>
          </div>
          <div class="mt-[12px] flex justify-between text-[14px]">
            <div
              class="left-meta flex items-center cursor-pointer"
              @click.stop="viewUser(product.user)">
              <img
                :src="product?.user?.avatar"
                class="w-[24px] h-[24px] rounded-full"
                :alt="product.user?.name" />
              <div
                class="text-[#222] ml-[4px] max-w-[100px] overflow-hidden text-ellipsis whitespace-nowrap"
                style="
                  max-width: 100px;
                  overflow: hidden;
                  text-overflow: ellipsis;
                  white-space: nowrap;
                ">
                {{ product.user?.name }}
              </div>
            </div>
            <div class="right-meta flex items-center">
              <div class="flex items-center gap-[4px]">
                <svg
                  v-like-pulse
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  :fill="isLiked(product) ? '#FF4D4F' : 'none'"
                  @click.stop="handleLike(product)"
                  :style="likingIds.has(product.id) ? 'pointer-events:none;opacity:0.6' : ''">
                  <path
                    d="M12.0005 21C11.6994 20.9996 11.4054 20.9086 11.1568 20.7389C7.47286 18.2381 5.87771 16.5234 4.99786 15.4514C3.12286 13.1663 2.22521 10.8202 2.25052 8.27953C2.28005 5.36813 4.61583 3 7.4574 3C9.52365 3 10.9547 4.16391 11.7882 5.13328C11.8146 5.16368 11.8472 5.18805 11.8838 5.20476C11.9205 5.22146 11.9603 5.23011 12.0005 5.23011C12.0408 5.23011 12.0806 5.22146 12.1172 5.20476C12.1538 5.18805 12.1865 5.16368 12.2129 5.13328C13.0463 4.16297 14.4774 3 16.5436 3C19.3852 3 21.721 5.36812 21.7505 8.28C21.7758 10.8211 20.8772 13.1672 19.0032 15.4519C18.1233 16.5239 16.5282 18.2386 12.8443 20.7394C12.5955 20.9089 12.3016 20.9998 12.0005 21Z"
                    :fill="isLiked(product) ? '#FF4D4F' : '#CBCBCB'" />
                </svg>
                <span class="font-[500]">{{ formatNumber(product.counter?.like_count) }}</span>
              </div>
              <div class="flex items-center gap-[4px] ml-[12px]">
                <svg
                  v-svg-hover
                  class="base_svg_color"
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  fill="currentColor"
                  viewBox="0 0 24 24">
                  <path
                    d="M17.7054 5.0025C16.084 3.70526 14.0692 2.99898 11.9928 3C9.54512 3 7.25896 3.94299 5.54977 5.6554C3.89803 7.31237 2.99281 9.50009 3.00004 11.814C3.0001 13.5104 3.49814 15.1696 4.43241 16.5856L4.44004 16.5964C4.45129 16.6129 4.46294 16.6294 4.47459 16.6454C4.48624 16.6615 4.50071 16.6824 4.50392 16.6876L4.51276 16.7037C4.55816 16.7841 4.59312 16.8821 4.56218 16.9809L3.82209 19.6592C3.79249 19.7588 3.77627 19.8619 3.77388 19.9658C3.77335 20.2391 3.8812 20.5014 4.07378 20.6953C4.26637 20.8891 4.52798 20.9987 4.80124 21C4.94564 20.9952 5.08795 20.964 5.22111 20.908L7.93275 19.9292L7.96691 19.916C8.04067 19.885 8.11994 19.8693 8.19994 19.8698C8.2737 19.87 8.34682 19.8836 8.4157 19.91C8.48079 19.9353 9.07181 20.1615 9.69538 20.3358C10.2137 20.4805 11.2921 20.6975 12.137 20.6975C14.5337 20.6975 16.7716 19.7693 18.4382 18.0834C20.0904 16.4104 21 14.1865 21 11.8188C21.0002 11.211 20.9358 10.6049 20.8079 10.0108C20.3925 8.05728 19.2908 6.27817 17.7054 5.0025ZM8.14289 13.2857C7.8886 13.2857 7.64002 13.2103 7.42859 13.069C7.21715 12.9278 7.05236 12.727 6.95505 12.492C6.85773 12.2571 6.83227 11.9986 6.88188 11.7492C6.93149 11.4998 7.05394 11.2707 7.23375 11.0909C7.41356 10.9111 7.64265 10.7886 7.89206 10.739C8.14146 10.6894 8.39997 10.7148 8.63491 10.8122C8.86984 10.9095 9.07064 11.0743 9.21192 11.2857C9.35319 11.4971 9.4286 11.7457 9.4286 12C9.4286 12.341 9.29314 12.668 9.05202 12.9091C8.8109 13.1503 8.48388 13.2857 8.14289 13.2857ZM12 13.2857C11.7457 13.2857 11.4972 13.2103 11.2857 13.069C11.0743 12.9278 10.9095 12.727 10.8122 12.492C10.7149 12.2571 10.6894 11.9986 10.739 11.7492C10.7886 11.4998 10.9111 11.2707 11.0909 11.0909C11.2707 10.9111 11.4998 10.7886 11.7492 10.739C11.9986 10.6894 12.2571 10.7148 12.492 10.8122C12.727 10.9095 12.9278 11.0743 13.0691 11.2857C13.2103 11.4971 13.2857 11.7457 13.2857 12C13.2857 12.341 13.1503 12.668 12.9092 12.9091C12.668 13.1503 12.341 13.2857 12 13.2857ZM15.8572 13.2857C15.6029 13.2857 15.3543 13.2103 15.1429 13.069C14.9314 12.9278 14.7666 12.727 14.6693 12.492C14.572 12.2571 14.5465 11.9986 14.5961 11.7492C14.6458 11.4998 14.7682 11.2707 14.948 11.0909C15.1278 10.9111 15.3569 10.7886 15.6063 10.739C15.8557 10.6894 16.1142 10.7148 16.3492 10.8122C16.5841 10.9095 16.7849 11.0743 16.9262 11.2857C17.0675 11.4971 17.1429 11.7457 17.1429 12C17.1429 12.341 17.0074 12.668 16.7663 12.9091C16.5252 13.1503 16.1981 13.2857 15.8572 13.2857Z" />
                </svg>
                <span class="font-[500]">{{ formatNumber(product.counter?.comment_count) }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 加载更多状态（移出瀑布流容器，跟随文档流，显示在内容之后） -->
    <div v-if="loadMoreLoading" class="load-more-container">
      <div class="load-more-spinner">
        <svg
          class="animate-spin"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg">
          <circle
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            stroke-width="4"
            stroke-dasharray="31.416"
            stroke-dashoffset="31.416">
            <animate
              attributeName="stroke-dasharray"
              dur="2s"
              values="0 31.416;15.708 15.708;0 31.416"
              repeatCount="indefinite" />
            <animate
              attributeName="stroke-dashoffset"
              dur="2s"
              values="0;-15.708;-31.416"
              repeatCount="indefinite" />
          </circle>
        </svg>
        <span class="load-more-text">Loading more...</span>
      </div>
    </div>

    <!-- 没有更多数据提示（移出瀑布流容器，显示在内容末尾） -->
    <div
      v-else-if="!hasMore && products?.length > 0 && !loading && !loadMoreLoading"
      class="no-more-container">
      <div class="no-more-text">
        <div class="lline"></div>
        <div>No more</div>
        <div class="lline"></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, onMounted, onUnmounted, nextTick, watch, onActivated } from 'vue';
  import type { FeedItem, FeedsParams } from '@/api/feeds';
  import { CommentAPI } from '@/api/comment';
  import { useRouter } from 'vue-router';
  import { useUserStore } from '@/store/user';
  import { useLoginModal } from '@/composables/useLoginModal';
  const router = useRouter();
  const userStore = useUserStore();
  interface Props {
    products: FeedItem[];
    loading?: boolean;
    loadMoreLoading?: boolean;
    hasMore?: boolean;
  }
  const isLoggedIn = computed(() => userStore.isAuthenticated);
  const userInfo = computed(() => userStore.user);

  const props = withDefaults(defineProps<Props>(), {
    products: () => [],
    loading: false,
    loadMoreLoading: false,
    hasMore: true,
  });

  // 计算属性
  const hasProducts = computed(() => props.products && props.products.length > 0);

  // 瀑布流相关
  const masonryContainer = ref<HTMLElement>();
  const columnCount = ref(5);
  const columnHeights = ref<number[]>([]);
  const processedItems = ref<Set<number>>(new Set()); // 记录已处理的元素
  const isInitialized = ref(false); // 是否已初始化
  let containerResizeObserver: ResizeObserver | null = null; // 监听容器尺寸变化

  // 简易防抖
  const debounce = (fn: (...args: any[]) => void, delay = 120) => {
    let timer: number | null = null;
    return (...args: any[]) => {
      if (timer) window.clearTimeout(timer);
      timer = window.setTimeout(() => {
        fn(...args);
        timer = null;
      }, delay);
    };
  };

  // 点赞/取消点赞逻辑
  const likingIds = ref<Set<number>>(new Set());

  const isLiked = (product: FeedItem) => {
    return product.like_flag === 1;
  };

  const handleLike = async (product: FeedItem) => {
    const id: any = product.feed_id;
    if (likingIds.value.has(id)) return;

    likingIds.value.add(id);
    try {
      if (!isLiked(product)) {
        // 点赞
        await CommentAPI.isLike({ feed_id: id, liked_uid: product.uid });
        // 乐观更新状态
        product.like_flag = 1;
        if (product.counter && typeof product.counter.like_count === 'number') {
          product.counter.like_count += 1;
        }
      } else {
        // 取消点赞
        await CommentAPI.unLike({ feed_id: id, liked_uid: product.uid });
        // 乐观更新状态
        product.like_flag = 0;
        if (
          product.counter &&
          typeof product.counter.like_count === 'number' &&
          product.counter.like_count > 0
        ) {
          product.counter.like_count -= 1;
        }
      }
    } catch (error) {
      console.error('点赞操作失败:', error);
      // 发生错误时恢复原状态
      product.like_flag = isLiked(product) ? 0 : 1;
    } finally {
      likingIds.value.delete(id);
    }
  };

  // 方法
  const viewProduct = (product: FeedItem) => {
    if (!isLoggedIn.value || !userInfo.value) {
      const { showModal } = useLoginModal();
      showModal();
      return;
    }
    router.push({ path: '/detail', query: { feed_id: product?.feed_id } });
  };

  // 处理标签点击事件
  const handleTagClick = (tag: any) => {
    // 当tag_type=1时，跳转到活动详情页
    if (tag.tag_type === 1) {
      router.push({ path: '/contest/detail', query: { aid: tag.target_id } });
    } else {
      // 其他类型标签的处理逻辑（如有需要）
      console.log('点击了其他类型的标签:', tag);
    }
  };

  // 重置瀑布流状态（用于搜索或切换Tab时）
  const resetMasonry = () => {
    processedItems.value.clear();
    isInitialized.value = false;
    columnHeights.value = [];
    if (masonryContainer.value) {
      masonryContainer.value.style.height = 'auto';
    }
  };

  const formatNumber = (num: number) => {
    if (!num) return '0';
    if (num >= 1000) {
      return (num / 1000).toFixed(1) + 'k';
    }
    return num.toString();
  };

  const getImageStyle: any = (thumbnail: any) => {
    if (!masonryContainer.value || !thumbnail) {
      return {};
    }

    // 计算项目宽度（与positionItem函数中相同的计算方式）
    const containerWidth = masonryContainer.value.offsetWidth;
    const horizontalGap = 24; // 横向间距 24px
    const itemWidth =
      (containerWidth - (columnCount.value - 1) * horizontalGap) / columnCount.value;

    // 计算图片比例
    const hasValidDimensions = thumbnail.width && thumbnail.height && thumbnail.width > 0;
    const aspectRatio = hasValidDimensions ? thumbnail.width / thumbnail.height : 1; // 默认1:1比例

    // 根据比例计算高度
    const calculatedHeight = itemWidth / aspectRatio;

    return {
      width: '100%',
      height: `${calculatedHeight}px`,
      objectFit: 'cover', // 确保图片按比例填充
    };
  };

  // 瀑布流布局函数
  const initMasonry = () => {
    if (!masonryContainer.value) return;

    const container = masonryContainer.value;
    const items = container.querySelectorAll('.masonry-item');

    // 如果是首次初始化，重置列高度
    if (!isInitialized.value) {
      columnHeights.value = new Array(columnCount.value).fill(0);
      isInitialized.value = true;
    }

    // 重置容器高度
    container.style.height = 'auto';

    let loadedCount = 0;
    const totalItems = items.length;

    const processItem = (htmlItem: HTMLElement, productId: number) => {
      // 检查是否已经处理过这个元素
      if (processedItems.value.has(productId)) {
        return;
      }

      positionItem(htmlItem);
      processedItems.value.add(productId);
      loadedCount++;

      // 每次放置后都更新容器高度，避免尾部提示提前浮上来
      nextTick(() => {
        const maxHeight = Math.max(...columnHeights.value);
        container.style.height = `${maxHeight}px`;
      });
    };

    items.forEach((item: Element, index: number) => {
      const htmlItem = item as HTMLElement;
      const productId = props.products[index]?.id || index;

      // 如果已经处理过，跳过
      if (processedItems.value.has(productId)) {
        return;
      }

      // 先设置占位高度，防止布局塌陷
      htmlItem.style.minHeight = '200px'; // 设置最小高度占位
      htmlItem.classList.add('loading'); // 添加加载状态类

      const image = htmlItem.querySelector('img') as HTMLImageElement;
      processItem(htmlItem, productId);

      if (image) {
        // 图片加载成功
        const handleImageLoad = () => {
          htmlItem.classList.remove('loading'); // 移除加载状态类
          nextTick(() => {
            processItem(htmlItem, productId);
          });
        };

        // 图片加载失败
        const handleImageError = () => {
          console.warn('图片加载失败:', image.src);
          htmlItem.classList.remove('loading'); // 移除加载状态类
          nextTick(() => {
            processItem(htmlItem, productId);
          });
        };

        // 设置超时处理，防止图片永远不加载
        const timeout = setTimeout(() => {
          console.warn('图片加载超时:', image.src);
          handleImageError();
        }, 10000); // 10秒超时

        // 绑定事件
        image.onload = () => {
          clearTimeout(timeout);
          handleImageLoad();
        };

        image.onerror = () => {
          clearTimeout(timeout);
          handleImageError();
        };

        // 如果图片已经加载完成
        if (image.complete) {
          clearTimeout(timeout);
          handleImageLoad();
        }
      } else {
        // 没有图片的情况，直接定位
        htmlItem.classList.remove('loading');
        nextTick(() => {
          processItem(htmlItem, productId);
        });
      }
    });
  };

  // 仅做重新排版（不等待图片加载）
  const relayoutMasonry = () => {
    if (!masonryContainer.value) return;

    const container = masonryContainer.value;
    const items = container.querySelectorAll('.masonry-item');

    // 重置列高度
    columnHeights.value = new Array(columnCount.value).fill(0);

    items.forEach((item: Element) => {
      positionItem(item as HTMLElement);
    });

    nextTick(() => {
      const maxHeight = Math.max(...columnHeights.value);
      container.style.height = `${maxHeight}px`;
    });
  };

  const positionItem = (item: HTMLElement) => {
    if (!masonryContainer.value) return;

    // 找到最短的列
    const shortestColumnIndex = columnHeights.value.indexOf(Math.min(...columnHeights.value));

    // 计算位置和间距
    const containerWidth = masonryContainer.value.offsetWidth;
    const horizontalGap = 24; // 横向间距 24px
    const verticalGap = 32; // 纵向间距 32px

    // 计算每个项目的宽度（考虑横向间距）
    const itemWidth =
      (containerWidth - (columnCount.value - 1) * horizontalGap) / columnCount.value;
    const left = shortestColumnIndex * (itemWidth + horizontalGap);
    const top = columnHeights.value[shortestColumnIndex];

    // 设置位置
    item.style.position = 'absolute';
    item.style.left = `${left}px`;
    item.style.top = `${top}px`;
    item.style.width = `${itemWidth}px`;
    item.style.opacity = '0'; // 初始透明
    item.style.transform = 'translateY(20px)'; // 初始向下偏移

    // 更新列高度（加上纵向间距）
    columnHeights.value[shortestColumnIndex] += item.offsetHeight + verticalGap;

    // 添加进入动画
    nextTick(() => {
      item.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
      item.style.opacity = '1';
      item.style.transform = 'translateY(0)';
    });
  };

  const updateColumnCount = () => {
    if (!masonryContainer.value) return;

    const containerWidth = masonryContainer.value.offsetWidth;
    let newColumnCount = 2; // 默认设为最小列数
    //  6 1920 5 1440 4 1280 3 720 2
    if (containerWidth < 720) {
      newColumnCount = 2;
    } else if (containerWidth < 1280) {
      newColumnCount = 3;
    } else if (containerWidth < 1440) {
      newColumnCount = 4;
    } else if (containerWidth < 1920) {
      newColumnCount = 5;
    } else {
      newColumnCount = 6; // 超大屏幕显示6列
    }

    if (newColumnCount !== columnCount.value) {
      columnCount.value = newColumnCount;
      // 列数变化，做一次完整重排
      nextTick(() => {
        relayoutMasonry();
      });
    } else {
      // 列数不变但宽度变化，也需要重排
      nextTick(() => {
        relayoutMasonry();
      });
    }
  };

  const handleResize = debounce(() => {
    updateColumnCount();
  }, 120);

  // 生命周期
  onMounted(() => {
    nextTick(() => {
      initMasonry();
      window.addEventListener('resize', handleResize);

      // 监听容器宽度变化（例如侧栏开合、父级布局变化）
      if ('ResizeObserver' in window && masonryContainer.value) {
        const onContainerResize = debounce(() => {
          updateColumnCount();
        }, 120);
        containerResizeObserver = new ResizeObserver(onContainerResize);
        containerResizeObserver.observe(masonryContainer.value);
      }
    });
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
    if (containerResizeObserver) {
      containerResizeObserver.disconnect();
      containerResizeObserver = null;
    }
  });

  // 监听 products 变化，只处理新增的数据
  watch(
    () => props.products,
    (newProducts, oldProducts) => {
      const oldLength = oldProducts?.length || 0;
      const newLength = newProducts?.length || 0;

      if (newLength > oldLength) {
        // 产品数量增加，说明有新数据加载，只处理新增的
        nextTick(() => {
          // initMasonry();
          relayoutMasonry();
        });
      } else if (newLength < oldLength) {
        resetMasonry();
        nextTick(() => {
          initMasonry();
        });
      }
    },
    { deep: true }
  );

  // 查看用户
  const viewUser = (user: any) => {
    router.push({ path: '/profile', query: { uid: user?.uid } });
  };

  onActivated(() => {
    // initMasonry();
  });
</script>

<style lang="scss" scoped>
  @use '@/styles/variables' as *;

  .line {
    display: inline-block;
    background-image: linear-gradient(to right, #cbcbcb, #cbcbcb);
    background-size: 100% 2px;
    background-position: bottom;
    background-repeat: no-repeat;
  }

  .product-container {
    padding: 24px;
    position: relative;
    padding-bottom: 10px;
  }

  .masonry-container {
    position: relative;
    width: 100%;
    // min-height: 60vh;
  }

  .masonry-item {
    position: absolute;
    width: calc(25% - 12px); // 考虑16px横向间距
    overflow: hidden;
    transition: all 0.3s ease;
    cursor: pointer;
    border-radius: 8px;
    overflow: hidden;
    // 加载状态样式
    &.loading {
      opacity: 0.7;
      background: #f5f5f5;

      &::before {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 24px;
        height: 24px;
        border: 2px solid #e0e0e0;
        border-top: 2px solid #f76b1b;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        z-index: 1;
      }
    }
  }

  @keyframes spin {
    0% {
      transform: translate(-50%, -50%) rotate(0deg);
    }
    100% {
      transform: translate(-50%, -50%) rotate(360deg);
    }
  }

  .product-card {
    overflow: hidden;
    transition: all 0.3s ease;
    cursor: pointer;
  }

  .product-image {
    width: 100%;
    overflow: hidden;
    border-radius: 8px;

    img {
      width: 100%;
      height: auto;
      object-fit: cover;
      display: block;
      overflow: hidden;
      border-radius: 8px;
    }
  }

  .product-info {
    padding-top: 12px;
  }

  .product-name {
    color: #222;

    font-size: 14px;
    font-style: normal;
    font-weight: 600;
    line-height: normal;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .product-description {
    color: #7a7a7a;

    font-size: 14px;
    font-style: normal;
    font-weight: 400;
    line-height: normal;
    margin-top: 4px;
    display: flex;
    align-items: center;
  }

  .icon_huo {
    border-radius: 30px 0 0 30px;
    background: rgba(255, 255, 255, 0.4);
    backdrop-filter: blur(2px);
    display: inline-flex;
    padding: 8px 12px;
    align-items: center;
    gap: 16px;
  }

  .loading-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 200px;
  }

  .loading-text {
    font-size: 16px;
    color: #7a7a7a;
  }

  .empty-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 200px;
  }

  .empty-text {
    font-size: 16px;
    color: #7a7a7a;
  }

  .load-more-container {
    position: static; // 跟随文档流
    display: flex;
    justify-content: center;
    padding: 24px 0;
  }

  .load-more-spinner {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 24px;
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(10px);
    border-radius: 24px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    color: #666;
    font-size: 14px;

    font-weight: 500;
  }

  .load-more-text {
    white-space: nowrap;
  }

  .no-more-container {
    position: static; // 跟随文档流
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 32px 0; // 较大内边距，和内容保持距离
  }

  .no-more-text {
    padding: 12px 24px;
    color: #7a7a7a;
    font-size: 14px;

    font-weight: 500;
    text-align: center;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .lline {
    width: 60px;
    height: 1px;
    border-radius: 5px;
    background-color: #e1e2e3;
  }

  // 响应式设计
  @media (max-width: 1200px) {
    .masonry-item {
      width: calc(33.333% - 11px); // 3列，考虑16px间距
    }
  }

  @media (max-width: 968px) {
    .masonry-item {
      width: calc(50% - 8px); // 2列，考虑16px间距
    }
  }

  @media (max-width: 640px) {
    .masonry-item {
      width: 100%; // 1列，无需考虑间距
    }

    .product-container {
      padding: 20px 0;
    }
  }
  .tag_list_view {
    white-space: nowrap;
    /* 2. 超出容器部分隐藏 */
    overflow: hidden;
    /* 3. 超出部分用省略号代替 */
    text-overflow: ellipsis;
    flex: 1;
  }
</style>
